package top.jiangqiang.qyblog.core.storage.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.thread.ExecutorBuilder;
import lombok.extern.slf4j.Slf4j;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.http.SdkHttpResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.S3Configuration;
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
import software.amazon.awssdk.services.s3.model.DeleteObjectResponse;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import top.jiangqiang.qyblog.common.config.GlobalProperties;
import top.jiangqiang.qyblog.core.domain.StorageProperties;
import top.jiangqiang.qyblog.core.domain.entity.File;
import top.jiangqiang.qyblog.core.domain.entity.Storage;
import top.jiangqiang.qyblog.core.storage.AbstractS3StorageClient;

import java.io.InputStream;
import java.net.URI;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

@Slf4j
public class S3AsyncStorageClient extends AbstractS3StorageClient<S3AsyncClient> {
    private final ExecutorService executorService = ExecutorBuilder.create().setCorePoolSize(3).setMaxPoolSize(100).build();

    public S3AsyncStorageClient(Storage storage, GlobalProperties globalProperties) {
        super(storage, globalProperties);
        this.client = buildS3AsyncClient(storage.getConfig());
    }

    @Override
    public boolean test() {
        try {
            this.client.listBuckets();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean test(StorageProperties storageProperties) {
        try (S3AsyncClient s3AsyncClient = buildS3AsyncClient(storageProperties)) {
            try {
                s3AsyncClient.listBuckets();
                return true;
            } catch (Exception e) {
                return false;
            }
        }
    }

    @Override
    public void upload(File file, InputStream inputStream, Consumer<File> completeCallback) {
        // 创建 PutObjectRequest 请求
        PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                .bucket(properties.getBucket())
                .key(file.getFileKey())
                .build();
        AsyncRequestBody requestBody = AsyncRequestBody.fromInputStream(inputStream, file.getSize(), executorService);
        client.putObject(putObjectRequest, requestBody).whenComplete((response, throwable) -> {
            if (throwable != null) {
                file.setState(3);
            } else {
                // 检查上传结果
                SdkHttpResponse sdkHttpResponse = response.sdkHttpResponse();
                if (sdkHttpResponse.isSuccessful()) {
                    file.setState(1);
                } else {
                    file.setState(3);
                }
            }
            completeCallback.accept(file);
        });
    }

    @Override
    public boolean delete(String fileKey) {
        DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder()
                .bucket(properties.getBucket())
                .key(fileKey)
                .build();
        try {
            DeleteObjectResponse response = client.deleteObject(deleteObjectRequest).get();
            SdkHttpResponse sdkHttpResponse = response.sdkHttpResponse();
            return sdkHttpResponse.isSuccessful();
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public void close() {
        log.debug("关闭当前存储器，存储器配置:{}", properties);
        IoUtil.close(this.client);
        // 等待线程池终止
        try {
            if (!executorService.awaitTermination(3, TimeUnit.SECONDS)) {
                // 如果超时仍未终止，可以调用 shutdownNow() 方法进行强制关闭
                executorService.shutdownNow();
            }
        } catch (Exception e) {
            log.debug("关闭线程池出现异常：{}", e.getMessage());
        }
    }

    /**
     * properties.setAccessKey("1AKIDtjNsY7i520xoefkosy1tZ7SRjwCVpBxm");
     * properties.setAccessSecret("2wsgXRLJIHHYqva9ZmkU6GDvPkvsaAanl");
     * properties.setBucket("test-1256657221");
     * properties.setEndpoint("cos.ap-shanghai.myqcloud.com");
     *
     * @param properties
     * @return
     */
    public static S3AsyncClient buildS3AsyncClient(StorageProperties properties) {
        return S3AsyncClient.builder()
                .region(Region.of(properties.getRegion()))
                .endpointOverride(URI.create(properties.getEndpointProtocol() + "://" + properties.getEndpoint()))
                .credentialsProvider(() -> AwsBasicCredentials.create(properties.getAccessKey(), properties.getAccessSecret()))
                .serviceConfiguration(S3Configuration.builder()
                        .chunkedEncodingEnabled(false)
                        .pathStyleAccessEnabled(properties.getEnablePathStyleAccess())
                        .build())
                .build();
    }

}
